package com.navinfo.tripanalysis.offline.service.impl.huashen;

import com.navinfo.location.mileage.bean.MileageAndFuel;
import com.navinfo.tripanalysis.common.pojo.Point;
import com.navinfo.tripanalysis.common.pojo.Point0200;
import com.navinfo.tripanalysis.common.pojo.RunningType;
import com.navinfo.tripanalysis.common.pojo.RunningTypeEnum;
import com.navinfo.tripanalysis.common.util.ArithmeticUtils;
import com.navinfo.tripanalysis.common.util.CommonUtils;
import com.navinfo.tripanalysis.offline.pojo.PreTripInfo;
import com.navinfo.tripanalysis.offline.service.PreTripInfoService;
import com.navinfo.tripanalysis.offline.util.TripStatisticUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 行程切分
 * @author web
 */
@RunningType(value = RunningTypeEnum.HS, interfaceClass =PreTripInfoService.class )
public class PreTripInfoServiceImpl implements PreTripInfoService {

    /**
     * 精准切分转速阀值
     */
    private final int PRECISE_ROTATION_THRESHOLD = 100;

    /**
     * 根据0200切分行程
     * 1）根据当天0200点，按发动机转速>100切分出子行程，统计出行程开始、结束时间及行程时长
     * 2）根据子行程的开始结束时间，切分出对应的0f37及0200的子数据
     * 3) 根据0200的子行程调用精准里程油耗算法算出子行程的精准里程、精准油耗
     * @param points0f37
     * @param points0200
     * @param day 当前日期
     * @return
     */
    public List<PreTripInfo> preJudgeTrip(List<Point> points0f37, List<Point0200> points0200, Date day) {
        List<PreTripInfo> list = new ArrayList<>();

        //只根据0200切分行程
        if (CommonUtils.isCollectionNotEmpty(points0200)) {
            PreTripInfo preTripInfo = null;
            Long lastGpsTime = null;
            int tripId = 0;

            for (Point0200 pojo : points0200) {
                long gpsTime = pojo.getGpsTime();

                int status = judgeTripStatus(lastGpsTime, gpsTime, pojo.getRotation());
                if (TRIP_START==status || TRIP_IN==status) {
                    if (preTripInfo == null) {
                        preTripInfo = handleStart(++tripId, pojo);
                    }
                    pojo.setTripId(preTripInfo.getTripId());
                    preTripInfo.getSubPoints0200().add(pojo);
                    lastGpsTime = gpsTime;
                } else {
                    if (preTripInfo != null) {
                        pojo.setTripId(preTripInfo.getTripId());
                        preTripInfo.getSubPoints0200().add(pojo);
                        handleEnd(points0f37, list, preTripInfo, status, day);
                    }

                    //清空状态
                    preTripInfo = null;
                    lastGpsTime = null;
                }
            }

            handleEnd(points0f37, list, preTripInfo,null, day);
        }

        return list;
    }

    @Override
    public List<PreTripInfo> judgeTrip(List<Point> points0f37, List<Point0200> points0200, Date day){
        List<PreTripInfo> preTripInfoList = PreTripInfoService.super.judgeTrip(points0f37, points0200, day);

        preTripInfoList.forEach(preTripInfo -> {
            //根据0200点计算精准里程和精准油耗
            MileageAndFuel mileageAndFuel = TripStatisticUtils.calcMileageFuel(RunningTypeEnum.HS, preTripInfo.getSubPoints0200());
            preTripInfo.setPreciseFuel(ArithmeticUtils.fuelLToMl(mileageAndFuel.getStdFuelCon()));
            preTripInfo.setPreciseMileage(ArithmeticUtils.mileageKMToM(mileageAndFuel.getStdMileage()));
        });

        return  preTripInfoList;
    }

    @Override
    public void handleEnd(List<Point> points0f37, List<PreTripInfo> list, PreTripInfo preTripInfo, Integer status, Date day){
        PreTripInfoService.super.handleEnd(points0f37, list, preTripInfo, status, day);

        if(null != preTripInfo){
            //根据0200点计算精准里程和精准油耗
            MileageAndFuel mileageAndFuel = TripStatisticUtils.calcMileageFuel(RunningTypeEnum.HS, preTripInfo.getSubPoints0200());
            preTripInfo.setPreciseFuel(ArithmeticUtils.fuelLToMl(mileageAndFuel.getStdFuelCon()));
            preTripInfo.setPreciseMileage(ArithmeticUtils.mileageKMToM(mileageAndFuel.getStdMileage()));
        }
    }


    /**
     * 判断行程状态
     * @param lastGpsTime 上一个point时间
     * @param gpsTime      当前point时间
     * @param rotation
     * @return
     */
    private int judgeTripStatus(Long lastGpsTime, long gpsTime, long rotation) {
        //行程未开始
        if (lastGpsTime == null) {
            return rotation>PRECISE_ROTATION_THRESHOLD ? TRIP_START : TRIP_NO_START;
        }
        //行程已开始
        else {
            if (isForceEnd(lastGpsTime, gpsTime)) {
                return TRIP_FORCE_END;
            } else {
                return rotation>PRECISE_ROTATION_THRESHOLD ? TRIP_IN : TRIP_END;
            }
        }
    }
}
